package com.icebergteam.warfacewidget.videos.data;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;

import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import android.app.NotificationManager;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.support.v4.app.NotificationCompat;
import com.icebergteam.warfacewidget.AppManager;
import com.icebergteam.warfacewidget.R;
import com.icebergteam.warfacewidget.WidgetProvider;
import com.icebergteam.warfacewidget.core.LogManager;
import com.icebergteam.warfacewidget.core.Parser;
import com.icebergteam.warfacewidget.core.connection.NetworkManager;
import com.icebergteam.warfacewidget.core.utils.TimeDateUtils;
import com.icebergteam.warfacewidget.core.utils.ViewUtils;
import com.icebergteam.warfacewidget.data.sql.VideosTable;
import com.icebergteam.warfacewidget.ui.YouTubeVideoPlayerActivity;

public class VideosParser extends Parser  {
	final public static String className = VideosParser.class.getCanonicalName();
	final public static String PATTERN_DATE = "[0-3]\\d/[01]\\d/\\d{4} - ([01]?[0-9]|2[0-3]):[0-5][0-9]";
	final public static String FORMAT_DATE = "dd/MM/yyyy - hh:mm";
	
	public VideosParser(boolean restoreKey) {
		super(restoreKey);
	}

	public VideosParser() {
		super();
	}

	@Override
	public int saveData(String url) throws Exception {
		try {
			if (this.isRestoreKey() && AppManager.getDatabase().getVideosTable().getCount()>0){
				LogManager.LogV(VideosParser.className, LogManager.getExecuteMethodName(),
						"generate restore");
				throw new Exception(WidgetProvider.RESTORE_ACTION); 
			}
			LogManager.LogVA(VideosParser.className, url);
			this.setRestoreKey(false);
			this.doc = Jsoup.parse(NetworkManager.getResponseInputStream(url), "UTF-8", "");
			parseXML(doc, -1);

			this.stateRequest = VideosParser.REQUEST_COMPLETED;
			LogManager.LogV(VideosParser.className,  LogManager.getExecuteMethodName(), url);

		} catch (SocketTimeoutException e) {
			LogManager.LogE(VideosParser.className,  LogManager.getExecuteMethodName(), "timeout", url); 
			e.printStackTrace();
			restore(VideosParser.REQUEST_FAILED | VideosParser.LIST_RESTORED,
										VideosParser.REQUEST_FAILED | VideosParser.LIST_RESTORED);
		} catch (IOException e) {
			LogManager.LogE(VideosParser.className,  LogManager.getExecuteMethodName(), url, e.getMessage());
			e.printStackTrace();
			restore(VideosParser.REQUEST_FAILED | VideosParser.LIST_RESTORED,
								VideosParser.REQUEST_FAILED);
		}catch (SQLException e) {
			LogManager.LogE(VideosParser.className,  LogManager.getExecuteMethodName(), url, e.getMessage());
			e.printStackTrace();
			this.stateRequest = VideosParser.DB_INVALID;
			
		}catch (Exception e) {
			LogManager.LogE(VideosParser.className,  LogManager.getExecuteMethodName(), url,
					e.getLocalizedMessage());
			
			if (WidgetProvider.RESTORE_ACTION.equals(e.getMessage())) {
				restore(VideosParser.LIST_RESTORED, VideosParser.REQUEST_FAILED);
			}
			else{
				this.stateRequest = (VideosParser.REQUEST_FAILED);
				e.printStackTrace();
			}
		}
		return this.stateRequest;
	}

	@Override
	protected	void  restore(int complete, int failed)	throws Exception {
		try {
			int count = AppManager.getDatabase().getVideosTable().getCount();
			
			if(count == -1){
				throw new Exception( LogManager.getExecuteMethodName() + " - DB empty");
			}
		
			this.stateRequest = complete;
			LogManager.LogV(VideosParser.className,  LogManager.getExecuteMethodName());
		}catch (SQLException e) {
			e.printStackTrace();
			throw new SQLException(String.format(
					"%s - error = %s",  LogManager.getExecuteMethodName(), e.getMessage()));
		}catch (Exception e1) {
			e1.printStackTrace();
			this.stateRequest = failed;
	
			throw new Exception(String.format(
					"%a - error = %s",  LogManager.getExecuteMethodName(),e1.getMessage()));
		}
	}
	
	@Override
	public ArrayList<VideosItem> parseXML(Document doc, int limit) throws Exception {
		try {
		
			Elements listItems = doc.select("div.blockcontent div.view div.view-content div.item-list li");
			LogManager.LogVA(className, listItems.size());
			
			ArrayList<VideosItem> newsList = new ArrayList<VideosItem>();
			
			NotificationManager mNotifyManager =
			        (NotificationManager) AppManager.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
			NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(AppManager.getContext());
			mBuilder.setContentTitle(AppManager.getContext().getString(R.string.videos_thumbnails_download))
			    .setContentText(AppManager.getContext().getString(R.string.in_progress))
			    .setSmallIcon(R.drawable.ic_launcher)
			    .setOngoing(true);
			
			int index =0;
			
			int size = (limit>=0)? limit: listItems.size();
			for (Element item: listItems) {
				newsList.add(getItem(item));
				index++;
				mBuilder.setProgress(100, index * 100 / size, false);
                mNotifyManager.notify(0, mBuilder.build());
             	if(limit >= 0 && index == limit) break;
			}
			return newsList;
		} 
		catch (SQLException e) {
			e.printStackTrace();
			throw new SQLException(String.format(
					"%s - doc = %s; error = %s",  LogManager.getExecuteMethodName(), (doc == null) ? doc == null :doc.toString().substring(0, Math.min(doc.toString().length(), 200)),
					e.getMessage()));
		}
		catch (Exception e) {
			e.printStackTrace();
			this.stateRequest = VideosParser.XML_INVALID;

			throw new Exception(String.format(
					"%s - doc = %s; error = %s",  LogManager.getExecuteMethodName(), (doc == null) ? doc == null :doc.toString().substring(0, Math.min(doc.toString().length(), 200)),
					e.getMessage()));
		}
	}
	
	@Override
	protected VideosItem getItem(org.jsoup.nodes.Element elem) throws Exception {
		
		VideosItem item = new VideosItem();
		
		try{
			item.setTitle(elem.select("div.views-field-title span.field-content").first().text());		
			item.setUrl(ViewUtils.fixUrlString("http://wf.mail.ru/" + elem.select("a.imagecache").first().attr("href")));
			
			String url = item.getUrl();
			
			Cursor videosItemCursor = AppManager.getDatabase().getVideosTable().getVideosByUrl(url);
			
			if(!videosItemCursor.moveToFirst()){
							
			
				LogManager.LogVA(VideosParser.className, url);
				
				
				VideosItem videoItemFromPage = parseVideoPage(Jsoup.parse(NetworkManager.getResponseInputStream(url), "UTF-8", ""));
				
				item.setImgSrc(ViewUtils.getSourcePath(elem.select("img").first().attr("src"), WidgetProvider.VIDEOS_PATH, ViewUtils.TYPE_MEDIA, true));
				item.setVideoUrl(videoItemFromPage.getVideoUrl());	
				item.setPubdate(videoItemFromPage.getPubdate());
				item.setRead(false);
				
				ContentValues dataToInsert = new ContentValues();    
				dataToInsert.put(VideosTable.FIELD_TITLE, item.getTitle());
				dataToInsert.put(VideosTable.FIELD_URL, url);
				dataToInsert.put(VideosTable.FIELD_IMGSRC, item.getImgSrc());
				dataToInsert.put(VideosTable.FIELD_VIDEO_URL, item.getVideoUrl());
				dataToInsert.put(VideosTable.FIELD_PUBDATE, item.getPubdate());
				dataToInsert.put(VideosTable.FIELD_READ, false);
				
				AppManager.getDatabase().getVideosTable().updateOrInsert(dataToInsert);
				
				dataToInsert = null;
				videoItemFromPage = null;
			}
			else{
				item.setImgSrc(videosItemCursor.getString(videosItemCursor.getColumnIndex(VideosTable.FIELD_IMGSRC.trim())));
				item.setVideoUrl(videosItemCursor.getString(videosItemCursor.getColumnIndex(VideosTable.FIELD_VIDEO_URL.trim())));
				item.setPubdate(videosItemCursor.getLong(videosItemCursor.getColumnIndex(VideosTable.FIELD_PUBDATE.trim())));
				item.setRead(videosItemCursor.getInt(videosItemCursor.getColumnIndex(VideosTable.FIELD_READ.trim())));
			}
			
			videosItemCursor = null;
			LogManager.LogVA(className, item);
		
		}
		catch (Exception e) {
			e.printStackTrace();
			
			LogManager.LogEA(className, item, e.getLocalizedMessage());
			return null;
		}
		return item;
	}
	private VideosItem parseVideoPage(Element elem) throws Exception{
		VideosItem item = new VideosItem();
				
		item.setPubdate(TimeDateUtils.getTimestampFromString(FORMAT_DATE, PATTERN_DATE, elem.select("span.submitted div.username").first().text()));
		item.setVideoUrl(YouTubeVideoPlayerActivity.getYoutubeID( (elem.select("object, iframe").first()) ,true));
	
		return item;
	}

	@Override
	public Object parseXML(JSONObject doc, int limit) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}
}